<?php
namespace app\logic;

use think\exception\ValidateException;
use think\facade\Validate;
use file\localfile\Localfile;
use file\alioss\Alioss;

class Upload extends Base
{
    protected $config;
    // 初始化
    protected function initialize()
    {
        parent::initialize();
        $this->model = new \app\model\Upload();
        $this->config = get_config('upload');
    }

    /**
     * 获取文件分页列表
     * @param array $where
     * @param string $field
     * @return array
     */
    public function getList($where = [], $field = "*")
    {
        $page = $where['page'] ?? 1;
        $limit = $where['limit'] ?? 10;

        // 删除无用参数
        if(isset($where['page'])) unset($where['page']);
        if(isset($where['limit'])) unset($where['limit']);

        $result = $this->model::where($where)
            ->field($field)
            ->order('id', 'desc')
            ->paginate([
                'page'      => $page,
                'list_rows' => $limit
            ]);

        return [config('status.success'), "ok", $result];
    }

    /**
     * 获取文件信息
     * @param array $where
     * @param string $field
     */
    public function getInfo($where = [], $field = "*")
    {
        return $this->model::where($where)
            ->field($field)
            ->find();
    }

    /**
     * 上传文件
     * @param $file
     * @param string $path
     * @return array
     */
    public function upload($file, $path = "storage")
    {
        // 文件验证
        try {
            // 上传限制大小
            $file_size = !empty($this->config['file_size']) ? ($this->config['file_size']*1024*1024) : (5*1024*1024);
            // 允许后缀
            $file_ext = $this->config['file_ext'] ?? "jpg,png,jpeg,iec";
            Validate::rule([
                'file'  => "fileSize:$file_size|fileExt:$file_ext"
            ])->failException(true)->check(['file' => $file]);
        } catch (ValidateException $e) {
            return [config('status.verify'), $e->getError()];
        }
        // 获取配置->文件上传类型 ---- 待完善
        $config_upload_type = $this->config['file_type'] ?? "local";
        // 上传文件
        $up_result = $this->uploadFile($config_upload_type, $file, $path);
        if($up_result === false) {
            return [config('status.fail'), "上传失败"];
        }

        // 保存文件
        $this->saveFile($file, $up_result, $config_upload_type);

        return [config('status.success'), "上传成功", [
            'src' => $up_result ?? "未知"
        ]];
    }

    /**
     * 按类型上传文件, 完成返回文件路径
     * @param $type
     * @param $file
     * @param string $path
     * @return bool|string
     */
    public function  uploadFile($type, $file, $path = "storage")
    {
        if($type == "local") {
            // ******** 本地上传 start ********
            $file_result = Localfile::uploadFile($file, $path);
            if($file_result['status'] === false) {
                // 记录本地上传错误日志
                trace('[本地上传]'. $file_result['msg'], 'error');
                return false;
            }
            $file_path = $file_result['href'];
            // ******** 本地上传 end ********
        } elseif ($type == "alioss") {
            // ******** 阿里云 OSS start 上传 ********
            // 1.先传本地
            $local_file_result = $this->uploadFile("local", $file, $path);
            if($local_file_result === false) {
                // 记录阿里云oss上传错误日志
                trace('[阿里云OSS]无法获取本地文件路径', 'error');
                return false;
            }
            // 2.获取阿里云oss配置->文件上传 ---- 待完善
            $alioss = new Alioss([
                'access_key_id'     => $this->config['alioss_accesskey_id'],
                'access_key_secret' => $this->config['alioss_accesskey_secret'],
                'endpoint'          => $this->config['oss_endpoint'],
                'bucket'            => $this->config['oss_bucket']
            ]);
            // 3. 传到阿里云
            $alioss_file_result = $alioss->uploadFile($local_file_result, $file->extension(), $path);
            // 4.上传完成删除本地文件
            Localfile::deleteFile([$local_file_result]);
            if ($alioss_file_result['status'] === false) {
                // 记录阿里云oss上传错误日志
                trace('[阿里云OSS]'. $alioss_file_result['msg'], 'error');
                return false;
            }
            $file_path = $alioss_file_result['href'];
            // ******** 阿里云 OSS end 上传 ********
        } else {
            return false;
        }

        return $file_path;
    }

    /**
     * 上传文件保存到数据库
     * @param $file Object 上传文件
     * @param $href String 路径
     * @param $type string 保存类型默认本地
     */
    public function saveFile($file, $href, $type = "local")
    {
        $data = [
            'name'  => $file->getOriginalName(),
            'type'  => $type,
            'href'  => $href,
            'mime'  => $file->getOriginalMime(),
            'size'  => round($file->getSize()/1024, 2), // 转换为 KB
        ];
        // 添加数据
        $this->model::create($data);
    }

    /**
     * 删除文件及数据
     * @param array $ids
     * @return array
     */
    public function delete($ids = [])
    {
        // 查询所有传入 ID 数据
        $list = $this->model::where('id', 'in',$ids)
            ->field('id,type,href')
            ->select();
        if(empty($list->toArray())) {
            return [config('status.fail'), "删除数据不存在"];
        }
        $list_type = [];
        // 数据分类
        foreach($list as $item) {
            $list_type[$item['type']]['ids'][] = $item['id'];
            $list_type[$item['type']]['href'][] = $item['href'];
        }
        // 删除本地文件及数据
        if(isset($list_type['local'])) {
            $result = Localfile::deleteFile($list_type['local']['href']);
            $result && $this->model::destroy($list_type['local']['ids']);
        }
        // 删除阿里云oss文件及数据
        if (isset($list_type['alioss'])) {
            // 获取阿里云oss配置->文件删除 ---- 待完善
            $alioss = new Alioss([
                'access_key_id'     => $this->config['alioss_accesskey_id'],
                'access_key_secret' => $this->config['alioss_accesskey_secret'],
                'endpoint'          => $this->config['oss_endpoint'],
                'bucket'            => $this->config['oss_bucket']
            ]);
            $result = $alioss->deleteFile($list_type['alioss']['href']);
            $result && $this->model::destroy($list_type['alioss']['ids']);
        }

        return [config('status.success'), "删除成功"];
    }
}